<#assign idColumn=table.idColumn>
<#assign sortColumn = table.modelType.getColumn("sort")>
<#assign parentColumn = table.modelType.getColumn("parent")>
<#assign pathColumn = table.modelType.getColumn("path")>
<#assign viewUrl=table.viewUrl>
$(function () {
    var Components = {
        init: function () {
            Components.searchBar.init();
            Components.dialogs.init();
            Components.forms.init();
            Components.dataTable.init();
        },
        searchBar: (function () {
            var treeObjMap = {};
            var treeDataMap = {};
            var privates = {
                initTreeMap: function () {
                    methods.form().find('.erp-input-tree').each(function () {
                        var treeObj = $(this).data('options')['treeObj'];
                        var treeName = $(this).attr('for');
                        treeObjMap[treeName] = treeObj;
                        treeDataMap[treeName] = treeObj.transformToArray(treeObj.getNodes());
                    });
                }
            };
            var methods = {
                init: function () {
                    methods.initEvents();
                },
                initEvents: function () {
                    var $wrapper = methods.wrapper();
                    $wrapper.on('click', '.js-button-search', methods.search);
                    $wrapper.on('click', '.js-button-reset', methods.reset);
                    $wrapper.on('click', '.js-button-more', methods.more);
                },
                search: function () {
                    Components.dataTable.render();
                },
                reset: function () {
                    var $form = methods.form();
                    $form[0].reset();
                    $form.find('[name]').val(null);
                    $form.find('.erp-input-tree').each(function () {
                        var treeObj = $(this).data('options')['treeObj'];
                        $.each(treeObj.getCheckedNodes(true), function () {
                            treeObj.checkNode(this, false);
                        });
                    });
                },
                more: function () {
                    var $wrapper = methods.wrapper();
                    $wrapper.find('.js-more-conditions').toggle();
                    $wrapper.find('span.glyphicon').toggle();
                },
                data: function (data) {
                    var $form = methods.form();
                    if (data && $.isPlainObject(data)) {
                        // load search form data
                        $form.extendLoadData(data);
                    } else {
                        // get search form data
                        var formData = {};
                        var $conditions = $('.js-search-condition');
                        $.each($conditions, function () {
                            var $this = $(this);
                            var forItems = $this.attr('for').split(',');
                            var cVal = $this.val();
                            $.each(forItems, function (idx, item) {
                                item = $.trim(item);
                                var $field = $form.find('[name="' + item + '"]');
                                var itemValue = $.trim($field.val());
                                if (itemValue) {
                                    // 上级查询
                                    var checkedNodes = $field.data('checked');
                                    if (checkedNodes && checkedNodes.length > 0) {
                                        cVal = cVal.replace('?' + idx, checkedNodes[0]['parentIds']);
                                    } else {
                                        cVal = cVal.replace('?' + idx, itemValue);
                                    }
                                }
                            });
                            if (-1 === cVal.indexOf('?')) {
                                formData[$this.attr('property')] = cVal;
                            }
                        });
                        return formData;
                    }
                },
                wrapper: function ()  {
                    return $('.js-searchBar-wrapper');
                },
                form: function () {
                    return methods.wrapper().find('form');
                },
                treeObj: function (treeName) {
                    if ($.isPlainObject(treeObjMap)) {
                        privates.initTreeMap();
                    }
                    return treeObjMap[treeName];
                },
                treeData: function (treeName) {
                    if ($.isPlainObject(treeDataMap)) {
                        privates.initTreeMap();
                    }
                    return treeDataMap[treeName];
                }
            };
            return methods;
        })(),
        dataTable: (function () {
            var _dataTable;
            var _dataMap;
            var methods = {
                init: function () {
                    // init data table
                    var defaults = $.dataTableCommons.getDefaults();
                    var options = {
                        paging: false,
                        columns: [
                            {data: null},
                            <#list table.columnsWithoutPrimaryKey as column>
                                <#if (column.name!=parentColumn.name && column.name!=pathColumn.name && column.name!=sortColumn.name)>
                            {data: '${column.property}'},
                                </#if>
                            </#list>
                            {data: null}
                        ],
                        ajax: function (data, callback, settings) {
                            var requestData = Components.searchBar.data();
                            $.ajax({
                                url: G_CONTEXT_PATH + '/${viewUrl}/by',
                                cache: false,
                                data: requestData,
                                dataType: 'json',
                                success: function (data) {
                                    if (!data || data.length === 0) {
                                        callback({data: [], recordsFiltered: 0});
                                        return;
                                    }
                                    // 缓存第一次的数据
                                    if (!methods.dataMap()) {
                                        methods.dataMap(data);
                                    }
                                    // 第一级节点
                                    var rootLevel = data[0]['parentIds'].split('/').length;
                                    var firstLevelNodes = [];
                                    $.each(data, function () {
                                        if (data[0]['parentId'] == this['parentId']) {
                                            firstLevelNodes.push(this);
                                        }
                                    });
                                    // 遍历第一级节点
                                    var matchedNodes = [];
                                    for (var i = 0; i < firstLevelNodes.length; i++) {
                                        matchedNodes.push(firstLevelNodes[i]);
                                        matchChildren(firstLevelNodes[i], data, matchedNodes);
                                    }
                                    // 匹配子节点
                                    function matchChildren(node, data, matchedNodes) {
                                        for (var i = 0; i < data.length; i++) {
                                            if (node['id'] == data[i]['parentId']) {
                                                matchedNodes.push(data[i]);
                                                matchChildren(data[i], data, matchedNodes);
                                            }
                                        }
                                    }

                                    // 通过添加空格在界面方便看出层级结构
                                    $.each(matchedNodes, function () {
                                        var level = this['parentIds'].split('/').length;
                                        this['__space__'] = '&nbsp;'.repeat((level - rootLevel) * 8);
                                    });
                                    // 回调渲染表格
                                    callback({data: matchedNodes, recordsFiltered: matchedNodes.length});
                                },
                                error: function (xhr, status, err) {
                                }
                            });
                        },
                        columnDefs: [{
                            targets: 0,
                            render: function (data, type, row) {
                                if ('/' === row['parentIds']) {
                                    return '';
                                }
                                return methods.wrapper().find('.js-check-column').html();
                            }
                        }, {
                            targets: 1,
                            render: function (data, type, row) {
                                return row['__space__'] + data;
                            }
                        }, {
                            targets: -1,
                            render: function (data, type, row) {
                                if ('/' === row['parentIds']) {
                                    return '';
                                }
                                return methods.wrapper().find('.js-action-column').html();
                            }
                        }]
                    };
                    _dataTable = methods.wrapper().find('table').DataTable($.extend(true, {}, defaults, options));
                    // init events
                    methods.initEvents();
                    return _dataTable;
                },
                initEvents: function () {
                    var $wrapper = methods.wrapper();
                    // create
                    $wrapper.on('click', '.js-button-create', Components.dialogs.create.show);
                    // update
                    $wrapper.on('click', '.js-button-update', function () {
                        // load form data
                        var rowData = methods.dataTable().row($(this).closest('tr')).data();
                        Components.forms.update.wrapper().extendLoadData(rowData);
                        // show dialog
                        Components.dialogs.update.show();
                    });
                    // check
                    $wrapper.on('click', 'table thead th:eq(0) :checkbox', function () {
                        var checked = this.checked;
                        $wrapper.find('table tbody tr').find('td:eq(0) :checkbox').each(function () {
                            this.checked = checked;
                        });
                        // toggle class
                        $wrapper.find('table tbody tr').toggleClass('selected', checked);
                    });
                    // click
                    $wrapper.on('click', 'table tbody tr td', function () {
                        if ($(this).children().hasClass('js-no-click')) {
                            return;
                        }
                        var ck = $(this).closest('tr').find('td:first :checkbox')[0];
                        ck['checked'] = !ck['checked'];
                        $(this).closest('tr').toggleClass('selected', ck['checked']);
                    });
                    // 删除
                    $wrapper.on('click', '.js-button-delete', function () {
                        // 检查是否有选中的记录
                        var $checked = $wrapper.find('table tbody tr').find('td:first :checked');
                        if ($checked.length === 0) {
                            layer.msg('请选择需要删除记录');
                            return;
                        }
                        // 获取选中记录的数据
                        var dataTable = methods.dataTable();
                        var rows = [];
                        var categoryRows = [];
                        $checked.each(function () {
                            var rowData = dataTable.row($(this).closest('tr')).data();
                            if ('category' === rowData['category']) {
                                categoryRows.push(rowData);
                            }
                            rows.push(rowData);
                        });
                        // 检查删除节点中是否包含父节点
                        var treeObj = Components.searchBar.treeObj('parentId');
                        var idKey = treeObj.setting.data.simpleData['idKey'];
                        var nameKey = treeObj.setting.data.key['name'];
                        var treeData = treeObj.transformToArray(treeObj.getNodes());
                        var ids = [];
                        for (var i = 0; i < rows.length; i++) {
                            var rowData = rows[i];
                            for (var j = 0; j < treeData.length; j++) {
                                if (rowData[idKey] === treeData[j][idKey]) {
                                    layer.msg('不能删除已包含子节点的父节点：【' + rowData[nameKey] + '】');
                                    return;
                                }
                            }
                            ids.push(rowData[idKey]);
                        }
                        // 确定删除
                        layer.alert('确定删除选中的记录？', function () {
                            $.ajax({
                                type: 'delete',
                                url: G_CONTEXT_PATH + '/${viewUrl}/' + ids,
                                cache: false,
                                dataType: 'json',
                                success: function (result) {
                                    layer.closeAll();
                                    dataTable.draw();
                                },
                                error: function (xhr, status, err) {
                                    layer.alert('操作发生异常，请联系管理员');
                                }
                            });
                        });
                    });
                    // 查看
                    $wrapper.on('click', '.js-button-view', function () {
                        // load data
                        var rowData = methods.dataTable().row($(this).closest('tr')).data();
                        var parent = rowData['parentId'];
                        var dataMap = Components.dataTable.dataMap();
                        Components.forms.view.wrapper().extendLoadData($.extend({}, rowData, {
                            parent: dataMap[parent] ? dataMap[parent]['name'] : null
                        }));
                        // show dialog
                        Components.dialogs.view.show();
                    });
                    // 移动
                    $wrapper.on('click', '.js-button-move', function () {
                        var $checked = $wrapper.find('table tbody tr').find('td:first :checked');
                        if ($checked.length === 0) {
                            layer.msg('请选择需要移动记录');
                            return;
                        }
                        if ($checked.length > 1) {
                            layer.msg('不能同时移动多条记录');
                            return;
                        }
                        var dataTable = methods.dataTable();
                        var direction = $(this).attr('direction');
                        // 找到同级节点
                        var siblingsMap = {};
                        var $from = $checked.closest('tr');
                        var fromData = dataTable.row($from).data();
                        var fromIndex;
                        var $rows = $from.closest('tbody').find('tr');
                        var siblingsCount = 0;
                        $rows.each(function () {
                            var $this = $(this);
                            var rowData = dataTable.row($this).data();
                            if (fromData['parentId'] === rowData['parentId']) {
                                siblingsMap[siblingsCount] = $this;
                                if (fromData['id'] === rowData['id']) {
                                    fromIndex = siblingsCount;
                                }
                                siblingsCount++;
                            }
                        });
                        // 找到目标节点
                        var toIndex;
                        var msg;
                        switch (direction) {
                            case 'up' :
                                toIndex = fromIndex - 1;
                                msg = '选中的记录是同级节点第一条记录，不能进行上移操作';
                                break;
                            case 'down' :
                                toIndex = fromIndex + 1;
                                msg = '选中的记录是同级节点最后一条记录，不能进行下移操作';
                                break;
                            case 'top' :
                                toIndex = 0;
                                msg = '选中的记录是同级节点第一条记录，不能进行置顶操作';
                                break;
                            case 'bottom' :
                                toIndex = siblingsCount - 1;
                                msg = '选中的记录是同级节点最后一条记录，不能进行置底操作';
                                break;
                        }
                        if (toIndex < 0 || toIndex >= siblingsCount || toIndex === fromIndex) {
                            layer.msg(msg);
                            return;
                        }
                        var toData = dataTable.row($(siblingsMap[toIndex])).data();
                        $.ajax({
                            url: G_CONTEXT_PATH + '/${viewUrl}/move/' + fromData['id'] + '/' + toData['id'],
                            type: 'put',
                            dataType: 'json',
                            cache: false,
                            success: function () {
                                methods.render();
                            }
                        });
                    });
                },
                render: function () {
                    methods.dataTable().draw();
                },
                wrapper: function ()  {
                    return $('.js-dataTable-wrapper');
                },
                dataMap: function (data) {
                    if (data) {
                        _dataMap = {};
                        $.each(data, function () {
                            _dataMap[this['id']] = this;
                        });
                    }
                    return _dataMap;
                },
                dataTable: function () {
                    return _dataTable;
                }
            };
            return methods;
        })(),
        dialogs: (function () {
            var defaults = {
                keyboard: false,
                backdrop: 'static',
                show: false
            };
            var privates = {
                onHidden: function (target) {
                    var $form = target.find('form');
                    $form.validate().resetForm();
                    var $helpBlock = $form.find('div.help-block');
                    $helpBlock.closest('.form-group').removeClass('has-error');
                    $helpBlock.remove();
                }
            };
            var methods = {
                init: function () {
                    methods.create.init();
                    methods.update.init();
                    methods.view.init();
                },
                create: (function () {
                    var methods = {
                        init: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.modal($.extend(true, {}, defaults))
                                .on('hidden.bs.modal', function (e) {
                                    privates.onHidden($wrapper);
                                })
                                .on('show.bs.modal', function () {
                                    var $form = $wrapper.find('form');
                                    var $inputTree = $form.find('.erp-input-tree');
                                    var options = $inputTree.data('options');
                                    var treeObj = options['treeObj'];
                                    // un check all node
                                    treeObj.checkAllNodes(false);
                                    var checkedNodes = treeObj.getCheckedNodes(true);
                                    $.each(checkedNodes, function () {
                                        if (this['checked']) {
                                            treeObj.checkNode(this, false);
                                        }
                                    });
                                    // un expand all node
                                    treeObj.expandAll();
                                    // expand first node
                                    treeObj.expandNode(treeObj.getNodes()[0]);
                                });
                            methods.initEvents();
                            return $wrapper;
                        },
                        initEvents: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.on('click', '.js-button-save', Components.forms.create.submit);
                        },
                        show: function () {
                            methods.wrapper().modal('show');
                        },
                        hide: function () {
                            methods.wrapper().modal('hide');
                        },
                        wrapper: function ()  {
                            return $('.js-dialog-create');
                        }
                    };
                    return methods;
                })(),
                update: (function () {
                    var methods = {
                        init: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.modal($.extend(true, {}, defaults))
                                .on('hidden.bs.modal', function (e) {
                                    privates.onHidden($wrapper);
                                    // show all node
                                    var $form = methods.wrapper().find('form');
                                    var $inputTree = $form.find('.erp-input-tree');
                                    var options = $inputTree.data('options');
                                    var treeObj = options['treeObj'];
                                    var hiddenNode = options['hiddenNode'];
                                    if (hiddenNode) {
                                        treeObj.showNode(hiddenNode);
                                    }
                                })
                                .on('show.bs.modal', function (e) {
                                    var $form = methods.wrapper().find('form');
                                    var $inputTree = $form.find('.erp-input-tree');
                                    var options = $inputTree.data('options');
                                    var treeObj = options['treeObj'];
                                    var idKey = treeObj.setting.data.simpleData['idKey'];
                                    var id = $form.find('[name="' + idKey + '"]').val();
                                    // hidden current node
                                    var node = treeObj.getNodesByParam(idKey, id)[0];
                                    treeObj.hideNode(node);
                                    options['hiddenNode'] = node;
                                    // selected parent node
                                    var parentName = $inputTree.attr('for');
                                    var parentId = $form.find('[name="' + parentName + '"]').val();
                                    var parentNode = treeObj.getNodesByParam(idKey, parentId)[0];
                                    treeObj.checkNode(parentNode, true, false);
                                    // set input tree text
                                    var nameKey = treeObj.setting.data.key['name'];
                                    $inputTree.val(parentNode[nameKey]);
                                    // expand parent node
                                    treeObj.expandNode(parentNode, true, false, false);
                                });
                            methods.initEvents();
                            return $wrapper;
                        },
                        initEvents: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.on('click', '.js-button-save', Components.forms.update.submit);
                        },
                        show: function () {
                            methods.wrapper().modal('show');
                        },
                        hide: function () {
                            methods.wrapper().modal('hide');
                        },
                        wrapper: function ()  {
                            return $('.js-dialog-update');
                        }
                    };
                    return methods;
                })(),
                view: (function () {
                    var methods = {
                        init: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.modal($.extend(true, {}, defaults))
                                .on('hidden.bs.modal', function (e) {
                                    $wrapper.find('form')[0].reset();
                                });
                            return $wrapper;
                        },
                        show: function () {
                            methods.wrapper().modal('show');
                        },
                        hide: function () {
                            methods.wrapper().modal('hide');
                        },
                        wrapper: function ()  {
                            return $('.js-dialog-view');
                        }
                    };
                    return methods;
                })()
            };
            return methods;
        })(),
        forms: (function () {
            var validateDefaults = $.validateCommons.getDefaults();
            var ajaxDefaults = {
                success: function (result, status, xhr) {
                    location.reload();
                },
                error: function (xhr, status, err) {
                    layer.alert('服务器出现异常，请联系管理员');
                }
            };
            var methods = {
                init: function () {
                    methods.create.init();
                    methods.update.init();
                    methods.view.init();
                },
                create: (function () {
                    var methods = {
                        init: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.validate($.extend(true, {}, validateDefaults));
                            return $wrapper;
                        },
                        submit: function () {
                            var $wrapper = methods.wrapper();
                            var ajaxOptions = $wrapper.extendAjaxOptions();
                            var merged = $.extend(true, {}, ajaxDefaults, ajaxOptions, {
                                beforeSend: function (xhr) {
                                    return $wrapper.valid();
                                }
                            });
                            $.ajax(merged);
                        },
                        wrapper: function ()  {
                            return Components.dialogs.create.wrapper().find('form');
                        }
                    };
                    return methods;
                })(),
                update: (function () {
                    var methods = {
                        init: function () {
                            var $wrapper = methods.wrapper();
                            $wrapper.validate($.extend(true, {}, validateDefaults));
                            return $wrapper;
                        },
                        submit: function () {
                            var $wrapper = methods.wrapper();
                            var ajaxOptions = $wrapper.extendAjaxOptions();
                            var merged = $.extend(true, {}, ajaxDefaults, ajaxOptions, {
                                beforeSend: function (xhr) {
                                    return $wrapper.valid();
                                }
                            });
                            $.ajax(merged);
                        },
                        wrapper: function ()  {
                            return Components.dialogs.update.wrapper().find('form');
                        }
                    };
                    return methods;
                })(),
                view: (function () {
                    var methods = {
                        init: function () {
                            return methods.wrapper();
                        },
                        wrapper: function ()  {
                            return Components.dialogs.view.wrapper().find('form');
                        }
                    };
                    return methods;
                })()
            };
            return methods;
        })()
    };
    Components.init();
});